﻿namespace FFF.Test.Application.PublicService.AppService.TreeGrid
{
    using System;
    using System.Collections.Generic;
    using System.IdentityModel.Tokens.Jwt;
    using System.IO;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Security.Claims;
    using System.Text;
    using System.Threading.Tasks;
    using Abp.Application.Services;
    using Abp.Application.Services.Dto;
    using Abp.Auditing;
    using Abp.Domain.Uow;
    using Abp.EntityFrameworkCore;
    using Abp.Runtime.Security;
    using Abp.Web.Models;
    using AutoMapper.Configuration;
    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.IdentityModel.Tokens;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Serialization;
    using FFF.Test.Application.AppServices;
    using FFF.Test.DataAccess.Framework;
    using FFF.Test.DataAccess.Framework.Configuration;
    using FFF.Test.Util.Configuration;
    using Ydm.Extensions;
    using Z.Expressions;

    /// <summary>
    /// Token的管理对象
    /// </summary>
    [YdmApiVersionAttribute(Version = "My")]
    public class TreeGridAppService : YdmAbpAppServiceBase, ITreeGridAppService
    {
        private readonly IDbContextProvider<MyDbContext> _dbContextProvider;

        /// <summary>
        /// Initializes a new instance of the <see cref="TreeGridAppService"/> class.
        /// toke构造方法初始化配置对象
        /// </summary>
        /// <param name="dbContextProvider">dbContextProvider</param>
        public TreeGridAppService(IDbContextProvider<MyDbContext> dbContextProvider)
        {
            this._dbContextProvider = dbContextProvider;
        }

        /// <summary>
        /// 获取Gird的数据
        /// </summary>
        /// <param name="pid">父级id</param>
        /// <param name="viewName">视图的名称</param>
        /// <param name="nodeName">展示节点属性的名称</param>
        /// <returns>grid</returns>
        [HttpPost]
        [Authorize(Roles = "admin")]
        [UnitOfWork(isTransactional: false)]
        public List<TreeGridOutDto> GetTreeGird(Guid? pid, string viewName, string nodeName)
        {
            MyDbContext db = this._dbContextProvider.GetDbContext();
            viewName = viewName.ToCamel();
            var views = $"db.{viewName}.Where(x=> x.ParentGUID==pid).ToList()".Execute<dynamic>(new { db, pid });
            List<TreeGridOutDto> result = new List<TreeGridOutDto>();
            foreach (var view in views)
            {
                TreeGridOutDto dto = new TreeGridOutDto()
                {
                    Id = (Guid)view.GetType().GetProperty("Id").GetValue(view),
                    Pid = (Guid?)view.GetType().GetProperty("ParentGUID").GetValue(view),
                    Code = (string)view.GetType().GetProperty("FullCode").GetValue(view),
                    Text = (string)view.GetType().GetProperty(nodeName).GetValue(view),
                    OrderCode = (string)view.GetType().GetProperty("OrderCode").GetValue(view)
                };

                bool isExistsChild = $"db.{viewName}.Any(x=> x.ParentGUID==dto.Id)".Execute<bool>(new { db, dto });
                if (!isExistsChild)
                {
                    dto.State = "open";
                }

                result.Add(dto);
            }

            return result;
        }

        /// <summary>
        ///  获取所有的父级的id 以,分割
        /// </summary>
        /// <param name="id">父级id</param>
        /// <param name="viewName">视图的名称</param>
        /// <returns>父级的id以,分割</returns>
        [HttpPost]
        [Authorize(Roles = "admin")]
        [UnitOfWork(isTransactional: false)]
        public string GetFatherIds(Guid id, string viewName)
        {
            MyDbContext db = this._dbContextProvider.GetDbContext();
            viewName = viewName.ToCamel();

            var view = $"db.{viewName}.FirstOrDefault(x => x.Id == id)".Execute<dynamic>(new { db, id });
            var excuteStr = $"db.{viewName}.Where(x => view.FullCode.Contains(x.FullCode) && view.FullCode != x.FullCode).Select(x => x.Id.ToString())";
            var ids = excuteStr.Execute<IQueryable<string>>(new { db, view });
            string result = string.Join(',', ids);
            return result;
        }

        ///// <summary>
        ///// 获取Gird的数据
        ///// </summary>
        ///// <param name="pid">父级id</param>
        ///// <param name="viewName">视图的名称</param>
        ///// <param name="nodeName">展示节点属性的名称</param>
        ///// <returns>grid</returns>
        //[HttpPost]
        //[Authorize(Roles = "admin")]
        //[UnitOfWork(isTransactional: false)]
        //public async Task<List<TreeGridOutDto>> GetTreeGird(Guid? pid, string viewName, string nodeName)
        //{
        //    MyDbContext db = this._dbContextProvider.GetDbContext();
        //    viewName = viewName.ToCamel();

        //    if (ViewConfiguration.ViewFullNames.Count == 0)
        //    {
        //        var s = await db.ViewDemoStudent.Where(x => 1 == 1).FirstOrDefaultAsync();
        //    }

        //    string viewFullName = ViewConfiguration.ViewFullNames.FirstOrDefault(x => x.Split(",")[0].EndsWith(viewName));
        //    Type curType = Type.GetType(viewFullName);

        //    PropertyInfo prop = db.GetType().GetProperty(viewName);

        //    object propVaule = prop.GetValue(db, null);

        //    MethodInfo method = typeof(Queryable).GetMethods().Where(x => x.Name == "Where").FirstOrDefault();
        //    MethodInfo generic = method.MakeGenericMethod(new Type[] { curType });

        //    var lambdaParam = Expression.Parameter(curType);

        //    var lambdaBody = Expression.Equal(
        //        Expression.PropertyOrField(lambdaParam, "ParentGUID"),
        //        Expression.Constant(pid, typeof(Guid?))
        //        );

        //    var exp = Expression.Lambda(lambdaBody, lambdaParam);

        //    var query = (IQueryable<object>)generic.Invoke(null, new object[] { propVaule, exp });
        //    var views = await query.ToListAsync();

        //    //var anyType = typeof(Func<,>).MakeGenericType(curType, typeof(bool));
        //    //var expAnyType = typeof(Expression<>).MakeGenericType(anyType);
        //    //var queryType = typeof(IQueryable<>).MakeGenericType(curType);

        //    // 构造any方法
        //    // MethodInfo anyMethod = typeof(Queryable).GetMethod("Any", new Type[] { queryType, expAnyType });

        //    MethodInfo anyMethod = typeof(Queryable).GetMethods().Where(x => x.Name == "Any").LastOrDefault();
        //    var anyMethodGen = anyMethod.MakeGenericMethod(new Type[] { curType });
        //    List<TreeGridOutDto> result = new List<TreeGridOutDto>();
        //    foreach (var view in views)
        //    {
        //        TreeGridOutDto dto = new TreeGridOutDto()
        //        {
        //            Id = (Guid)view.GetType().GetProperty("Id").GetValue(view),
        //            Pid = (Guid?)view.GetType().GetProperty("ParentGUID").GetValue(view),
        //            Code = (string)view.GetType().GetProperty("FullCode").GetValue(view),
        //            Text = (string)view.GetType().GetProperty(nodeName).GetValue(view),
        //            OrderCode = (string)view.GetType().GetProperty("OrderCode").GetValue(view)
        //        };

        //        lambdaBody = Expression.Equal(
        //        Expression.PropertyOrField(lambdaParam, "ParentGUID"),
        //        Expression.Constant(dto.Id, typeof(Guid?))
        //        );
        //        exp = Expression.Lambda(lambdaBody, lambdaParam);

        //        bool isExistsChild = (bool)anyMethodGen.Invoke(null, new object[] { propVaule, exp });
        //        if (!isExistsChild)
        //        {
        //            dto.State = "open";
        //        }

        //        result.Add(dto);
        //    }

        //    return result;
        //}

        ///// <summary>
        /////  获取所有的父级的id 以,分割
        ///// </summary>
        ///// <param name="id">父级id</param>
        ///// <param name="viewName">视图的名称</param>
        ///// <returns>父级的id以,分割</returns>
        //[HttpPost]
        //[Authorize(Roles = "admin")]
        //[UnitOfWork(isTransactional: false)]
        //public async Task<string> GetFatherIds(Guid id, string viewName)
        //{
        //    MyDbContext db = this._dbContextProvider.GetDbContext();
        //    viewName = viewName.ToCamel();

        //    if (ViewConfiguration.ViewFullNames.Count == 0)
        //    {
        //        var s = await db.ViewDemoStudent.Where(x => 1 == 1).FirstOrDefaultAsync();
        //    }

        //    string viewFullName = ViewConfiguration.ViewFullNames.FirstOrDefault(x => x.Split(",")[0].EndsWith(viewName));
        //    Type curType = Type.GetType(viewFullName);

        //    PropertyInfo prop = db.GetType().GetProperty(viewName);

        //    object propVaule = prop.GetValue(db, null);

        //    MethodInfo method = typeof(Queryable).GetMethods().Where(x => x.Name == "FirstOrDefault").LastOrDefault();
        //    MethodInfo generic = method.MakeGenericMethod(new Type[] { curType });

        //    var lambdaParam = Expression.Parameter(curType, "x");

        //    var lambdaBody = Expression.Equal(
        //        Expression.PropertyOrField(lambdaParam, "Id"),
        //        Expression.Constant(id, typeof(Guid))
        //        );

        //    var exp = Expression.Lambda(lambdaBody, lambdaParam);

        //    var entity = generic.Invoke(null, new object[] { propVaule, exp });
        //    var fullCode = entity.GetType().GetProperty("FullCode").GetValue(entity);

        //    var lambdaBody1 = Expression.NotEqual(
        //        Expression.PropertyOrField(lambdaParam, "FullCode"),
        //        Expression.Constant(fullCode, typeof(string))
        //      );

        //    var lambdaBody2 = Expression.Call(
        //        Expression.Constant(fullCode),
        //        typeof(string).GetMethod("Contains", new[] { typeof(string) }),
        //        Expression.Property(lambdaParam, "FullCode"));

        //    //var propertyExp = Expression.PropertyOrField(lambdaParam, "SchoolFullCode");
        //    //MethodInfo method2 = typeof(string).GetMethod("Contains", new[] { typeof(string) });
        //    //var someValue = Expression.Constant(fullCode, typeof(string));
        //    //var lambdaBody2 = Expression.Call(someValue, method, propertyExp);

        //    var lambdaBody3 = Expression.AndAlso(
        //       lambdaBody1,
        //       lambdaBody2
        //      );
        //    var expNew = Expression.Lambda(lambdaBody3, lambdaParam);

        //    method = typeof(Queryable).GetMethods().Where(x => x.Name == "Where").FirstOrDefault();
        //    generic = method.MakeGenericMethod(new Type[] { curType });

        //    var query = (IQueryable<object>)generic.Invoke(null, new object[] { propVaule, expNew });

        //    //method = typeof(Queryable).GetMethods().Where(x => x.Name == "Select").FirstOrDefault();
        //    //generic = method.MakeGenericMethod(new Type[] { curType, typeof(string) });
        //    //var lambdaBodySelect = Expression.Call(
        //    //                    Expression.PropertyOrField(lambdaParam, "Id"),
        //    //                    typeof(Guid).GetMethod("ToString", new Type[] { })
        //    //                 );

        //    // var ids = method.Invoke(null, new object[] { query, lambdaBodySelect });

        //    var ids = query.Select(x => x.GetType().GetProperty("Id").GetValue(x).ToString());
        //    var idsStr = string.Join(',', ids);

        //    return idsStr;
        //}
    }
}